/**

This file is part of MaCI/GIMnet.

MaCI/GIMnet is free software: you can redistribute it and/or modify it 
under the terms of the GNU Lesser General Public License as published 
by the Free Software Foundation, either version 3 of the License, or 
(at your option) any later version.

MaCI/GIMnet is distributed in the hope that it will be useful, but WITHOUT 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
License for more details.

You should have received a copy of the GNU Lesser General Public 
License along with GIMnet. (See COPYING.LESSER) If not, see 
<http://www.gnu.org/licenses/>.

**/
/**
 * \file
 * \brief Header for Wireless interface class.
 * \author Antti Maula <antti.maula@tkk.fi>
 */
#ifndef _MACI_WIRELESSTYPES_HPP_
#define _MACI_WIRELESSTYPES_HPP_
#include <inttypes.h>
#include "ownutils.h"
#include "owndebug.h"

namespace MaCI {

  /** MaCI - Wireless interface.
   *
   * This namespace contains all the methods and types related
   * to the Wireless interface.
   *
   * This interface is intended for operations / data related to
   * wireless links. For example; distributing information about
   * service providers known signal sources.
   */
  namespace Wireless {
    
    /** Enumeration types for Wireless data elements.
     */
    enum EWirelessType { 
      KTypeUnknown               = -1, ///< Unkown type.
      KTypeTimestamp             = 1,  ///< Common::TTimestamp element.
      KTypeCommand               = 2,  ///< TCommand element.
      KTypeNodeSignal            = 3,  ///< TNodeSignal element.
      KTypeNodeRange             = 4,  ///< TNodeRange element.
      KTypeNodePosition          = 5,  ///< TNodePosition element.
      KTypeNodeID     		 = 6,  ///< TNodeID element.
      KTypeMeasurementIndex      = 7,  ///< TMeasurementIndex element.
      KTypeWirelessChannel       = 8   ///< TWirelessChannel element.
    };
    
    
    /** Enumerations for Wireless Command.
     */
    enum EWirelessCommand { 
      /// Unknown command. This should never be sent.
      KCommandUnknown = 0
    };


    /** Wireless command.
     *
     * This structure contains command field to be used when sending
     * action requests to Wireless enabled clients.
     *
     * \see EWirelessCommand
     */
    struct TCommand 
    {
      TCommand(const unsigned int aCmd = 0,
               const unsigned int aData = 0) 
        : cmd(aCmd),
          data(aData) {}
      uint32_t cmd;             ///< Command
      uint32_t data;            ///< Data for command. (Is command specific)
    } __attribute__ ((packed, aligned (4)));



    struct TWirelessChannel
    {
      TWirelessChannel(const uint32_t aChannel = 0)
        :channel(aChannel){}

      uint32_t channel;

    }__attribute__ ((packed, aligned (4)));



    /** Signal strength of a single node.
     *
     * This structure contains information about a single node. It
     * includes a unsigned 32 bit identifier and signed 32 bit
     * signal_dbm field.
     */
    struct TNodeSignal {
      TNodeSignal(const uint64_t aNodeID = 0,
                  const int32_t aSignal = 0)

        : nodeid(aNodeID),
          signal_level(aSignal){}


      void Print(const int lvl) const {
        dPrint(lvl,"nodeid: 0x%llx, signal_level:%d",
               nodeid, signal_level);
      }

      uint64_t nodeid;          ///< Identifier for a node.
      int32_t signal_level;       ///< Signal strength.
      
    } __attribute__ ((packed, aligned (4)));
		
    /** Signal strength of a single node.
     *
     * This structure contains information about a single node. It
     * includes a unsigned 32 bit identifier and signed 32 bit
     * signal_dbm field.
     */
    struct TNodeID {
      TNodeID(const uint64_t aNodeID = 0,
              const char *aESSID = "")
        : nodeid(aNodeID),
          ESSID() {
        SetESSID(aESSID);
      }
      
      void Print(const int lvl) const {
        dPrint(lvl,"nodeid: 0x%llx, ESSID:%s",
               nodeid, ESSID);
      }
      void SetESSID(const char *aESSID) {
        strncpy(ESSID, aESSID, sizeof(ESSID));
        ESSID[sizeof(ESSID)-1] = '\0';
      }

      uint64_t nodeid;      ///< Identifier for a node.
      char ESSID[32];       ///< ESSID
    }__attribute__ ((packed, aligned (1))) ;

    /**
     * This structure contains information about the node measurement index. It informs only the index
     * number of the measurement. It can be used for example synchronising measurements of a two 
     * completely different systems(which have different timestamps) when processing the data off-line
     * 
     */
    struct TMeasurementIndex{
      TMeasurementIndex(uint32_t aMeasurementIndex =0)
        :measurementIndex(aMeasurementIndex){}

      uint32_t measurementIndex;
    } __attribute__ ((packed, aligned (4)));

    /** Range of a single node.
     *
     * This structure contains information about a single node. It
     * includes a unsigned 32 bit identifier and floating point value
     * for a distance in meters. Also, a variance field is provided
     * for storing quality information about the range.
     */
    struct TNodeRange {
      TNodeRange(const uint64_t aNodeID = 0,
                 const float aRange = 0.00,
                 const float aVariance = 0.00 )
        : nodeid(aNodeID),
          range(aRange),
          variance(aVariance) {}
      
      void Print(const int lvl) const {
        dPrint(lvl,"nodeid: 0x%llx, range:%f, variance:%f",
               nodeid, range, variance);
      }

      uint64_t nodeid;          ///< Identifier for a node.
      float range;              ///< Source range in meters.
      float variance;           ///< Range value variance estimate.
    } __attribute__ ((packed, aligned (4)));
    
    
    /** Position of a single node.
     *
     * This structure is intended for identifying the whereabouts of a
     * single signal source. It may be used for determining the
     * current location by merging information about known nodes, and
     * distances to them.
     *
     */
    struct TNodePosition {
      TNodePosition(const uint64_t aNodeID = 0,
                    const float aPosX = 0.00,
                    const float aPosY = 0.00,
                    const float aPosZ = 0.00)
        : nodeid(aNodeID),
          pos_x(aPosX),
          pos_y(aPosY),
          pos_z(aPosZ) {}

      void Print(const int lvl) const {
        dPrint(lvl,"nodeid: 0x%llx, pos_x:%f, pos_y:%f, pos_z:%f",
               nodeid, pos_x, pos_y, pos_z);
      }

      uint64_t nodeid;          ///< Identifier for a node.
      float pos_x;              ///< Position in the X axis.
      float pos_y;              ///< Position in the Y axis.
      float pos_z;              ///< Position in the Z axis.
    } __attribute__ ((packed, aligned (4)));

  }
}

#endif
